# -*- coding:utf-8 -*-
from datetime import datetime

from flask import request, abort, current_app, make_response, session, redirect

from info.utils.captcha_util import generate_captcha
from . import passport_blu
from ... import redis_store, constants, db
from ...libs.yuntongxun.sms import send_message
from ...models import User, LoginInfo
from ...utils import utils
from ...utils.resonse import info_jsonfy
from ...utils.response_code import RET


@passport_blu.route("/image_code")
def generate_cap():
    """
    生成图片验证码
    """
    # 从请求中获取imageCodeId
    imageCodeId = request.args.get("imageCodeId", None)
    # 如果未取到则报错
    if not imageCodeId:
        abort(403)
    # 生成图片验证码
    image, content = generate_captcha()
    current_app.logger.warning(f"\n{'-' * 100}\n图片验证码：{content}\n{'-' * 100}")
    # 将验证码存入redis中，并设置过期时间
    try:
        redis_store.set(name=f"imageCodeId:{imageCodeId}", value=content, ex=constants.IMAGE_CODE_REDIS_EXPIRES)
    except Exception as e:
        current_app.logger.error(e)  # 记录错误日志
        abort(500)
    # 构造响应并返回
    response = make_response(image)
    response.headers["Content-Type"] = "image/jpg"
    return response


@passport_blu.route("/sms_code", methods=["POST"])
def send_sms_code():
    """发送短信逻辑"""
    # 获取参数
    data_dict = request.json
    mobile = data_dict.get("mobile")
    imageCode = data_dict.get("imageCode")
    imageCodeId = data_dict.get("imageCodeId")

    # 校验参数
    # 校验是否有值
    if not all([mobile, imageCode, imageCodeId]):
        return info_jsonfy(RET.PARAMERR, "参数有误")
    # 校验手机号格式是否正确
    if not utils.check_mobile_format(mobile):
        return info_jsonfy(RET.PARAMERR, "手机号格式不正确")
    # 校验图片验证码是否正确
    try:
        realImageCode = redis_store.get(f"imageCodeId:{imageCodeId}")
    except Exception as e:
        current_app.logger.error(e)
        return info_jsonfy(RET.DBERR, "数据查询失败")

    if not realImageCode:
        return info_jsonfy(RET.NODATA, "验证码已过期")

    if realImageCode.upper() != imageCode.upper():
        return info_jsonfy(RET.DATAERR, "验证码输入错误")

    try:
        redis_store.delete(f"imageCodeId:{imageCodeId}")
    except Exception as e:
        current_app.logger.error(f"删除图片验证码Id:imageCodeId:{imageCodeId}失败\n" + str(e))

    # 发送短信
    smsCode = utils.random_character(cType="int", length=6)  # 生成手机验证码
    current_app.logger.warning(f"\n{'-' * 100}\n短信验证码：{smsCode}\n{'-' * 100}")
    try:
        redis_store.set(name=f"smsCode:{mobile}",
                        value=smsCode,
                        ex=constants.SMS_CODE_REDIS_EXPIRES)  # 将手机验证码保存到redis中
    except Exception as e:
        current_app.logger.error(e)
        return info_jsonfy(RET.DBERR, "数据库保存失败")

    result = send_message(1, mobile, (smsCode, constants.SMS_CODE_REDIS_EXPIRES // 60))
    if not result:
        return info_jsonfy(RET.THIRDERR, "发送短信失败")
    return info_jsonfy(RET.OK, "短信发送成功")


@passport_blu.route("/register", methods=["POST"])
def register():
    """注册逻辑"""
    # 获取参数
    data_dict = request.json
    mobile = data_dict.get("mobile")
    smsCode = data_dict.get("smscode")
    password = data_dict.get("password")

    # 校验参数
    # 校验是否有值
    if not all([mobile, smsCode,  password]):
        return info_jsonfy(RET.PARAMERR, "参数有误")
    # 校验手机号格式是否正确
    if not utils.check_mobile_format(mobile):
        return info_jsonfy(RET.PARAMERR, "手机号格式不正确")
    # 校验手机号是否存在
    try:
        user = User.query.filter(User.mobile == mobile).first()
    except Exception as e:
        current_app.logger.error(e)
        return info_jsonfy(RET.DBERR, "查询数据库失败")
    if user:
        return info_jsonfy(RET.DATAEXIST, "该手机号已注册")

    # 校验短信验证码是否正确
    try:
        realSmsCode = redis_store.get(f"smsCode:{mobile}")
    except Exception as e:
        current_app.logger.error(e)
        return info_jsonfy(RET.DBERR, "数据查询失败")

    if not realSmsCode:
        return info_jsonfy(RET.NODATA, "短信验证码已过期")

    if realSmsCode.upper() != smsCode.upper():
        return info_jsonfy(RET.DATAERR, "短信验证码输入错误")

    try:
        redis_store.delete(f"smsCode:{mobile}")
    except Exception as e:
        current_app.logger.error(f"删除短信验证码Id:smsCode:{mobile}失败\n" + str(e))

    # 添加用户到数据库
    user = User()
    user.id = utils.random_uuid()
    user.mobile = mobile
    user.password = password
    user.nick_name = mobile
    user.last_login = datetime.now()

    try:
        db.session.add(user)
        db.session.commit()
    except Exception as e:
        current_app.logger.error(e)
        db.session.rollback()
        return info_jsonfy(RET.DBERR, "数据库保存失败")

    userLoginInfo = LoginInfo()
    userLoginInfo.id = utils.random_uuid()
    userLoginInfo.user_id = user.id
    userLoginInfo.login_time = datetime.now()
    try:
        db.session.add(userLoginInfo)
        db.session.commit()
    except Exception as e:
        current_app.logger.error(e)
        db.session.rollback()
        return info_jsonfy(RET.DBERR, "数据库保存失败")

    # 添加session信息，完成注册即登录功能
    session["userId"] = user.id
    session["mobile"] = user.mobile
    session["nickName"] = user.nick_name

    # 返回响应
    return info_jsonfy(RET.OK, "注册成功")


@passport_blu.route("/login", methods=["POST"])
def login():
    """登录逻辑"""
    # 获取参数
    data_dict = request.json
    mobile = data_dict.get("mobile")
    password = data_dict.get("password")

    # 校验参数
    if not all([mobile, password]):
        return info_jsonfy(RET.PARAMERR, "参数错误")

    if not utils.check_mobile_format(mobile):
        return info_jsonfy(RET.PARAMERR, "手机号格式不正确")

    try:
        user = User.query.filter(User.mobile == mobile).first()
    except Exception as e:
        current_app.logger.error(e)
        return info_jsonfy(RET.DBERR, "数据库查询错误")

    if not user:
        return info_jsonfy(RET.NODATA, "用户不存在")

    if not user.check_password(password):
        return info_jsonfy(RET.PWDERR, "用户名或密码错误")

    # 保存session信息
    session["userId"] = user.id
    session["mobile"] = user.mobile
    session["nickName"] = user.nick_name
    if user.is_admin:
        session["isAdmin"] = True

    user.last_login = datetime.now()

    userLoginInfo = LoginInfo()
    userLoginInfo.id = utils.random_uuid()
    userLoginInfo.user_id = user.id
    userLoginInfo.login_time = user.last_login
    db.session.add(userLoginInfo)

    # 返回响应
    return info_jsonfy(RET.OK, "登录成功")


@passport_blu.route("/logout", methods=["GET"])
def logout():
    """退出登录"""
    isAdmin = session.get("isAdmin")
    session.clear()
    if isAdmin:
        return redirect("/admin/login")

    return info_jsonfy(RET.OK, "退出登录成功")
